package com.pimee.support.shiro.realm;

import java.util.HashSet;
import java.util.Set;

import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authc.UnknownAccountException;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.util.ByteSource;
import org.slf4j.LoggerFactory;

import com.alibaba.fastjson.JSONObject;
import com.pimee.common.util.SpringContextUtil;
import com.pimee.common.util.shiro.ShiroUtils;
import com.pimee.model.SysUser;
import com.pimee.service.admin.ISysMenuService;
import com.pimee.service.admin.ISysRoleService;
import com.pimee.service.admin.ISysUserService;
import com.pimee.support.shiro.security.UserToken;

import cn.hutool.core.util.ObjectUtil;

public class AdminShiroRealm extends AuthorizingRealm {
    private static org.slf4j.Logger logger = LoggerFactory.getLogger(AdminShiroRealm.class);

    //如果项目中用到了事物，@Autowired注解会使事物失效，可以自己用get方法获取值
//    @Autowired
//    private UserService userService;

    /**
     * 认证信息.(身份验证) : Authentication 是用来验证用户身份
     *
     */
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authcToken) throws AuthenticationException {
        logger.info("---------------- 执行 Shiro 凭证认证 ----------------------");
        ISysUserService sysUserService =  (ISysUserService) SpringContextUtil.getBean("sysUserService");
        UserToken token = (UserToken) authcToken;
        String userName = token.getUsername();
        String password = String.valueOf(token.getPassword());//登录密码
        // 从数据库获取对应用户名密码的用户
        SysUser sysUser = sysUserService.selectOneByAccount(userName);
        System.out.println("====> " + JSONObject.toJSONString(sysUser));
        if (ObjectUtil.isNull(sysUser)){
            throw new UnknownAccountException("帐号不存在！");
        }
        //交给AuthenticatingRealm使用CredentialsMatcher进行密码匹配，如果觉得人家的不好可以自定义实现
        return new SimpleAuthenticationInfo(
                sysUser, //用户名
                password, //密码
                ByteSource.Util.bytes(sysUser.getSalt()),//salt=username+salt
                getName()  //realm name
        );
    }

    /**
     * 授权
     */
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
        logger.info("---------------- 执行 Shiro 权限获取 ---------------------");
        
        ISysUserService sysUserService =  (ISysUserService) SpringContextUtil.getBean("sysUserService");
        ISysMenuService sysMenuService =  (ISysMenuService) SpringContextUtil.getBean("sysMenuService");
        ISysRoleService sysRoleService =  (ISysRoleService) SpringContextUtil.getBean("sysRoleService");
        SysUser user = ShiroUtils.getSysUser();
        // 角色列表
        Set<String> roles = new HashSet<>();
        // 功能列表
        Set<String> menus = new HashSet<>();
        SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
        // 管理员拥有所有权限
        if (sysUserService.isAdmin(user.getUserId())) {
            info.addRole("admin");
            info.addStringPermission("*:*:*");
        } else {
            roles = sysRoleService.selectRoleKeys(user.getUserId());
            menus = sysMenuService.selectPermsByUserId(user.getUserId());
            // 角色加入AuthorizationInfo认证对象
            info.setRoles(roles);
            // 权限加入AuthorizationInfo认证对象
            info.setStringPermissions(menus);
        }
        return info;
    }
    
    /**
     * 清理缓存权限
     */
    public void clearCachedAuthorizationInfo() {
        this.clearCachedAuthorizationInfo(SecurityUtils.getSubject().getPrincipals());
    }

}
